package components.fte
{
	import com.zn.utils.ClassUtil;
	import components.events.FTELinkEvent;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.net.getClassByAlias;
	import flash.text.engine.BreakOpportunity;
	import flash.text.engine.ContentElement;
	import flash.text.engine.ElementFormat;
	import flash.text.engine.FontDescription;
	import flash.text.engine.FontLookup;
	import flash.text.engine.FontPosture;
	import flash.text.engine.FontWeight;
	import flash.text.engine.GraphicElement;
	import flash.text.engine.GroupElement;
	import flash.text.engine.TextBaseline;
	import flash.text.engine.TextElement;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextLineMirrorRegion;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.getDefinitionByName;

	/**
	 *FTE 格式类
	 * @author zn
	 *
	 */
	public class FTEElement extends EventDispatcher
	{
		public var defaultFontName:String="宋体";

		public var defaultFontSize:Number=12;

		public var defaultFontColor:uint=0x000000;

		public var defaultBold:Boolean=false;
		
		public var defaultHGap:Number=0;

		protected var _fontName:String="";

		protected var _fontSize:Number=0;

		protected var _fontColor:int=-1;

		protected var _bold:Boolean=false;
		private var _hasBold:Boolean=false;
		
		protected var _hGap:Number=-1;


		public function FTEElement()
		{
		}

		public function createElement(value:String):GroupElement
		{
			XML.ignoreWhitespace=false;
			
			var valueXML:XML=FTEStrFormat.format(value);
			
			var list:Vector.<ContentElement>=new Vector.<ContentElement>();
			var xmlList:XMLList=valueXML.children();

			//设置段落格式
			if (valueXML.hasOwnProperty("@fontName"))
				_fontName=valueXML.@fontName;
			else
				_fontName="";

			if (valueXML.hasOwnProperty("@size"))
				_fontSize=valueXML.@size;
			else
				_fontSize=0;

			if (valueXML.hasOwnProperty("@color"))
				_fontColor=valueXML.@color;
			else
				_fontColor=-1;

			if (valueXML.hasOwnProperty("@bold"))
			{
				_bold=valueXML.@bold;
				_hasBold=true;
			}
			else
			{
				_bold=false;
				_hasBold=false;
			}
			
			if (valueXML.hasOwnProperty("@hGap"))
				_hGap=valueXML.@hGap;
			else
				_hGap=-1;

			//解析xml
			var itemXML:XML;
			for (var i:int=0; i < xmlList.length(); i++)
			{
				itemXML=xmlList[i];
				switch (itemXML.localName())
				{
					case "s":
					{
						list.push(getTextElement(itemXML));
						break;
					}
					case "g":
					{
						var g:ContentElement=getGraphicElement(itemXML);
						if (g)
							list.push(g);
						break;
					}
					case "a":
					{
						list.push(getLinkElement(itemXML));
						break;
					}
					case "n":
					{
						//换行
						list.push(getCRElement());
						break;
					}
				}
			}
			XML.ignoreWhitespace=true;
			return new GroupElement(list, null);
		}

		protected function getTextElement(xml:XML):ContentElement
		{
			var str:String=xml.toString();
			str=str.replace(/&amp;/g,"&");
			str=str.replace(/&gl;/g,"<");
			str=str.replace(/&gt;/g,"<");
			var textElement:TextElement=new TextElement(str, getFormat(xml));
			return textElement;
		}

		/**
		 *换行
		 * @return
		 *
		 */
		protected function getCRElement():ContentElement
		{
			var elementFormat:ElementFormat=getFormat(new XML());
			elementFormat.breakOpportunity=BreakOpportunity.AUTO;
			var textElement:TextElement=new TextElement("\n", elementFormat);
			return textElement;
		}

		protected function getGraphicElement(xml:XML):ContentElement
		{
			var displayObjectClass:Class;

			try
			{
				displayObjectClass=getClassByAlias(xml.toString());
			} 
			catch(error:Error) 
			{
				
			}
			
			try
			{
				if(displayObjectClass==null)
					displayObjectClass=Class(getDefinitionByName(xml.toString()));
			} 
			catch(error:Error) 
			{
				
			}
			if (displayObjectClass)
			{
				var displayObject:DisplayObject=new displayObjectClass();
				var ef:ElementFormat=new ElementFormat();
				ef.dominantBaseline=TextBaseline.IDEOGRAPHIC_CENTER;
				var graphicElement:GraphicElement=new GraphicElement(displayObject, displayObject.width, displayObject.height,ef );
				return graphicElement;
			}

			return null;
		}

		protected function getLinkElement(xml:XML):ContentElement
		{
			var eventValue:String;

			if (xml.hasOwnProperty("@value"))
				eventValue=xml.@value;
			else
				eventValue=xml.s[0].toString();

			var element:ContentElement=getTextElement(xml.s[0]);

			var myEvent:EventDispatcher=new EventDispatcher();

			myEvent.addEventListener(MouseEvent.CLICK, clickHandler);
			myEvent.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
			myEvent.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);

			element.eventMirror=myEvent;
			element.userData=eventValue;

			return element;
		}

		protected function getFormat(xml:XML):ElementFormat
		{
			var fontName:String;
			var fontSize:Number;
			var color:uint;
			var bold:Boolean;
			var hGap:Number;
			
			if (xml.hasOwnProperty("@fontName"))
				fontName=xml.@fontName;
			else if (_fontName != null && _fontName != "")
				fontName=_fontName;
			else
				fontName=defaultFontName;

			if (xml.hasOwnProperty("@size"))
				fontSize=xml.@size;
			else if (_fontSize != 0)
				fontSize=_fontSize;
			else
				fontSize=defaultFontSize;

			if (xml.hasOwnProperty("@color"))
				color=xml.@color;
			else if (_fontColor != -1)
				color=_fontColor;
			else
				color=defaultFontColor;

			if (xml.hasOwnProperty("@bold"))
				bold=xml.@bold;
			else if (_hasBold)
				bold=_bold;
			else
				bold=defaultBold;
			
			if (xml.hasOwnProperty("@hGap"))
				hGap=xml.@hGap;
			else if (_hGap != -1)
				hGap=_hGap;
			else
				hGap=defaultHGap;

			var fontWeight:String=FontWeight.NORMAL;
			if (bold)
				fontWeight=FontWeight.BOLD;

			var fontDescription:FontDescription=new FontDescription(fontName, fontWeight);
			var elementFormat:ElementFormat=new ElementFormat(fontDescription, fontSize, color);
			with (elementFormat)
			{
				dominantBaseline=TextBaseline.IDEOGRAPHIC_TOP;
				breakOpportunity=BreakOpportunity.ANY;
				trackingRight=hGap;
			}
			return elementFormat;
		}

		private function mouseOverHandler(event:MouseEvent):void
		{
			Mouse.cursor=MouseCursor.BUTTON;
		}

		private function mouseOutHandler(event:MouseEvent):void
		{
			Mouse.cursor=MouseCursor.AUTO;
		}

		protected function clickHandler(event:Event):void
		{
			var textLine:TextLine=event.currentTarget as TextLine;

			if (textLine)
			{
				var region:TextLineMirrorRegion;
				
				for (var i:int = 0; i < textLine.mirrorRegions.length; i++) 
				{
					region = TextLineMirrorRegion(textLine.mirrorRegions[i]);
					
					if(region.bounds.contains(textLine.mouseX,textLine.mouseY))
						dispatchEvent(new FTELinkEvent(region.element.userData));
				}
			}
		}
	}
}